/*
 * Send an HTTP request timeout period so we can do long async requests.
 * Not setting a timeout allows the browser to retry every few minutes.
 */
var RequestTimeout = 1000;

var http = require('http'),
      fs = require('fs'),
     url = require('url'),
 pathobj = require('path'),
 choices = ["hello world", "goodbye world"];

var exec  = require('child_process').exec;
var propc = require('./propellerc');
var loader= require('./loader');

var buildfile = "workspace/buildresult.txt";
var loadfile  = "workspace/loadresult.txt";
var sizefile  = "workspace/sizeresult.txt";

var portfile  = "workspace/portresult.txt";
var propver   = "Propeller Version 1 on ";

var isWindows= /^win/.test(process.platform);

var child = exec('date',
function(error, stdout, stderr) {
    console.log("Starting server.");
});

var tip = 0;

function winsep(str)
{
  if (isWindows) {
    while (str.indexOf('/') > -1) {
      str = str.replace('/','\\');
    }
    console.log(str);
  }
  return str;
}


function callbackReplyOk(response, error, stdout, stderr)
{
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end(stdout);
  if (error) console.log(error.code);
}

function saveSerialPort(str)
{
  var verpos = str.indexOf(propver);
  //console.log("Prop Version @ "+verpos);
  //console.log("'"+str+"'");
  if (verpos > 0) {
    console.log("Prop Version @ "+verpos);
    var portpos = verpos + propver.length;
    var newlpos = str.substr(portpos).indexOf("\n");
    if (newlpos < 0) {
      newlpos = str.substr(portpos).indexOf("\r");
    }
    //console.log("Port @ "+portpos);
    //console.log("Newl @ "+newlpos);
    var pname = str.substr(portpos,newlpos);
    console.log("Port '"+pname+"'");
    fs.writeFileSync(portfile, pname);
  }
}


var querystring = require('querystring');

http.createServer(
function(request, response)
{
    var path = url.parse(request.url).pathname;
    var date = new Date();

    // Tell the browser to resend requests just in cases the server misses one.
    // This is a hack to ensure that LoadResult always gets processed.
    request.setTimeout(1000);

    //console.log(date.toLocaleTimeString() + " " + path);

    if (path.indexOf("/FileList/") == 0) {
      var pwd = process.cwd();
      path = path.replace("/FileList","");
      path = pwd+"/workspace"+unescape(path);

      fs.readdir(path, function (err, files) {
        if (err) { 
          console.log("Can't read dir "+path);
          response.writeHead(200, { 'Content-Type': 'text/plain' });
          response.end("", "text/plain");
          //throw err;
        }
        else {
          var text ="";
          for (var n = 0; n < files.length; n++) {
            if(files[n].indexOf(".swp") > 0) continue;
            if ((files[n].indexOf(".c") > 0) || (files[n].indexOf(".h") > 0)) {
              //console.log(escape(files[n]));
              if (files[n] != "") text += "<option>"+(files[n])+"</option>";
            }
          }
          response.writeHead(200, { 'Content-Type': 'text/plain' });
          response.end(new Buffer(text), 'text/html');
        }
      });
    }
    else if (path.indexOf("/DeleteFile/") == 0) {
      path = path.replace("/DeleteFile","");
      path = "workspace"+unescape(path);

      console.log("PATH "+ path);

      if (request.method == "POST") {
        if (fs.existsSync(path)) fs.unlinkSync(path);
        response.writeHead(200, { 'Content-Type': 'text/plain' });
        response.end();
      }
    }
    else if (path.indexOf("/OpenFile/") == 0) {
      path = path.replace("/OpenFile","");
      path = "workspace"+unescape(path);

      fs.readFile(path, function (err, data) {
        if (err) { 
          console.log("Can't read file "+path);
          response.writeHead(200, { 'Content-Type': 'text/plain' });
          response.end("", "text/plain");
        }
        else {
          response.writeHead(200, { 'Content-Type': 'text/plain' });
          response.end(data, 'text/plain');
        }
      });
    }
    else if (path.indexOf("/SaveFile/") == 0) {
      path = path.replace("/SaveFile","");
      path = "workspace"+unescape(path);

      console.log("PATH "+ path);

      if (request.method == "PUT") {
        var data = "";
        request.on("readable", function() {
          //request.body = '';
          //while (null !== (request.body += request.read())){}
          data += request.read();
        });
        // Do something with it
        request.on("end", function saveFile(){
          console.log(data);
          fs.writeFile(path, data, function(err) {
            if (err) console.log("Error saving file: "+path);
          });
          response.writeHead(200, { 'Content-Type': 'text/plain' });
          response.end();
        });
      }
    }
    else if (path.indexOf("/SizeResult/") == 0) {
      if (fs.existsSync(sizefile)) {
        fs.readFile(sizefile, function (err, res) {
          var result = String(res);
          if (err) { 
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end();
          }
          else if (result.length < 1) {
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end();
          }
          else {
            console.log("SIZE_RESULT "+result);
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end(new Buffer(result), "text/plain");
          }
        });
      }
    }
    else if (path.indexOf("/BuildResult/") == 0) {
      if (fs.existsSync(buildfile)) {
        fs.readFile(buildfile, function (err, result) {
          if (err) { 
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end();
          }
          else if (result.length < 1) {
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end();
          }
          else {
            console.log("BUILD_RESULT "+result);
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end(new Buffer(result), "text/plain");
          }
        });
      }
    }
    else if (path.indexOf("/Build/") == 0) {
      path = path.replace("/Build","");
      path = "workspace"+unescape(path);
      var output = path.substr(0,path.lastIndexOf("."));

      //console.log("Build PATH "+ path +" "+output);
      if (fs.existsSync(buildfile)) fs.unlinkSync(buildfile);
      if (fs.existsSync(sizefile)) fs.unlinkSync(sizefile);
      if (fs.existsSync(loadfile)) fs.unlinkSync(loadfile);

      propc.build(path, function buildResult(error, stdout, stderr) {
        var result;
        if (stdout) {
          console.log(stdout);
        }

        if (error) {
          result = error;
        }
        else {
          result = "Build Succeeded!";
        }
        fs.writeFile(buildfile, result, function(err) {
          if (err) console.log("Error writing build result file: "+buildfile);
        });

        if (!error) {
          console.log("Now get program size.");
          var pwd = process.cwd();
          var cmd = winsep('propeller-elf-size "'+pwd+'/'+output+'"');

          exec(cmd, function(error, stdout, stderr) {
            if (error) {
              console.log("Error getting size.");
              fs.writeFile(sizefile, "", function(err) {
                if (err) console.log("Error writing size result file: "+sizefile);
              });
            }
            else {
              console.log(stdout);
              fs.writeFile(sizefile, stdout, function(err) {
                if (err) console.log("Error writing size result file: "+sizefile);
              });
            }
          });
        }
      });
            
      response.writeHead(200, { 'Content-Type': 'text/plain' });
      response.end("Building");
    }
    else if (path.indexOf("/LoadResult/") == 0) {
      console.log("/LoadResult/");
      if(fs.existsSync(loadfile)) {
        fs.readFile(loadfile, function (err, result) {
          if (err) { 
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end();
          }
          else if (result.length < 1) {
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end();
          }
          else if (result == "Load Succeeded!") {
            console.log("LOAD_RESULT "+result);
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end(new Buffer(result), "text/plain");
          }
          else {
            response.writeHead(200, { 'Content-Type': 'text/plain' });
            response.end(new Buffer(result), "text/plain");
          }
        });
      }
    }
    else if (path.indexOf("/LoadRAM/") == 0) {
      path = path.replace("/LoadRAM","");
      path = "workspace"+unescape(path);
      var file = path.substr(0,path.lastIndexOf("."));
      var verify = "Verifying RAM ...";

      console.log("LoadRAM "+file);

      if (fs.existsSync(loadfile)) fs.unlinkSync(loadfile);

      loader.loadRAM(file, function loadResult(error, stdout, stderr) {
        var result;
        if (stdout) {
          console.log(stdout);
        }
        if (error) {
          result = stdout+stderr;
          //result = "Load Failed!";
          fs.writeFile(loadfile, result, function(err) {
            if (err) console.log("Error writing load result file: "+loadfile);
          });
        }
        else if(stdout.indexOf(verify) > -1) {
          var s = stdout.substr(stdout.indexOf(verify)+verify.length);
          console.log(s);
          if (s.indexOf("error:") > 0) {
            result = "Load Failed!";
            fs.writeFile(loadfile, result, function(err) {
              if (err) console.log("Error writing load result file: "+loadfile);
            });
          }
          if (s.indexOf("OK") > 0) {
            saveSerialPort(stdout);
            result = "Load Succeeded!";
            fs.writeFileSync(loadfile, result);
          }
        }
      });
            
      response.writeHead(200, { 'Content-Type': 'text/plain' });
      response.end("Loading");
    }
    else if (path.indexOf("/LoadEEPROM/") == 0) {
      path = path.replace("/LoadEEPROM","");
      path = "workspace"+unescape(path);
      var file = path.substr(0,path.lastIndexOf("."));
      var verify = "Verifying EEPROM ...";

      console.log("LoadEEPROM "+file);

      if (fs.existsSync(loadfile)) fs.unlinkSync(loadfile);

      loader.loadEEPROM(file, function loadResult(error, stdout, stderr) {
        var result;
        if (stdout) {
          console.log(stdout);
        }
        if (error) {
          result = error;
        }
        else if(stdout.indexOf(verify) > -1) {
          var s = stdout.substr(stdout.indexOf(verify)+verify.length);
          console.log(s);
          if (s.indexOf("OK") > 0) {
            saveSerialPort(stdout);
            result = "Load Succeeded!";
            fs.writeFileSync(loadfile, result);
          }
        }
      });
            
      response.writeHead(200, { 'Content-Type': 'text/plain' });
      response.end("Loading");
    }
    else if (path.indexOf("/TxPort") == 0) {
    }
    else if (path.indexOf("/RxPort") == 0) {
    }
    else {
      var filename = pathobj.join(process.cwd(),path);
      if (fs.existsSync(filename)) {
        if(fs.statSync(filename).isDirectory()) {
          filename += 'index.html';
        }
        fs.readFile(filename, "binary", function(error, file) {
          if(error) {
            response.writeHead(500, { 'Content-Type': 'text/plain' });
            response.end(error+"\n", "utf-8");
            // write an error response or nothing here
            return;
          }
          var type = 'text/html';
          var fend = "utf-8";
          if(filename.substr(-3) == 'css') {
            type = 'text/css';
          }
          else if(filename.substr(-3) == 'png') {
            type = 'image/png';
            fend = "binary";
          }
          else if(filename.substr(-2) == 'js') {
            type = 'text/javascript';
          }
          response.writeHead(200, { 'Content-Type': type });
          response.end(file, fend);
          //console.log(filename + " " + type);
        });
      } else {
        response.writeHead(404, { 'Content-Type': 'text/plain' });
        response.end("404 Not Found", "utf-8");
      }
    }
}).listen(8051);

